
/*
    rust 闭包的特点
    闭包, 就是可以捕获其所在环境的匿名函数
    1. 首先是个匿名函数
    2. 可以不规定参数和返回值类型, 因为闭包是隐藏在局部的, 在狭小的上下文中运行
    3. 可以作为变量作为参数, 甚至作为返回值
 * 
 */
use std::{thread, time::Duration};

fn main() {
    let num = 12;
   test_fn(num);
   closure_test();

   // 注意, 闭包的定义只会为它的参数和返回值推断出唯一类型!
    let example_closure = |x| x;
    example_closure(4);
    // example_closure(String::from("jack")); // 这里便会报错, 因为闭包已经被定义为i32类型了
}

// 13.1内容(本案例目前仅仅只是将函数作为一个匿名函数赋给了变量, 其实还是存在问题
// 即 num < 25 的时候, 执行了两次函数 )
fn test_fn (num:u32) {
    // 此处声明了一个匿名函数
    let closure_fn = |num:u32| {
        println!("this is clousure start");
        thread::sleep(Duration::from_secs(2));
        num
    };
    if num < 25 {
        println!("num is: {}", closure_fn(2));
        println!("num is: {}", closure_fn(3));
    } else {
        if num > 26 && num < 50 {
            println!("this is 26")
        } else {
            println!("num is: {}", closure_fn(5))
        }
    }
}

// 13.2, 闭包的写法
// 不要求写上参数类型和返回类型, 理由:
// 1. 闭包不会被暴露给用户
// 2. 闭包只在一个狭窄的空间中运行, 编译器有能力保证类型推断的正确性
fn closure_test() {
    // 闭包的四种写法
    let closure1 = |num:u32| -> u32 {
        num + 1
    };
    let closure2 = |num| {
        num + 1
    };
    // 甚至花括号都可以省略
    let closure3 = |num| num + 1;

    fn closure4 (num: u32) -> u32 {
        num + 1
    }

    // 此时closure2会报错, 因为没有定义类型, 而当我们使用之后, 就没有错误了, 类型就能推出来了
    closure2(3);
    // closure3类似
    closure3(4);
}



